package edu.fiu.cis.personalize.server;

import it.sauronsoftware.feed4j.FeedParser;
import it.sauronsoftware.feed4j.bean.Feed;
import it.sauronsoftware.feed4j.bean.FeedItem;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.gwt.dev.util.collect.HashSet;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import edu.fiu.cis.personalize.client.PersonalizedSearchService;
import edu.fiu.cis.personalize.server.graph.NodeType;
import edu.fiu.cis.personalize.server.graph.Query;
import edu.fiu.cis.personalize.server.objectrank.NodeRef;
import edu.fiu.cis.personalize.server.objectrank.PersonalizedObjectRank;
import edu.fiu.cis.personalize.shared.GoogleDocument;
import edu.fiu.cis.personalize.shared.IBlock;
import edu.fiu.cis.personalize.shared.ManagedBlock;
import edu.fiu.cis.personalize.shared.QueryResult;
import edu.fiu.cis.personalize.shared.User;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class PersonalizedSearchServiceImpl extends RemoteServiceServlet
		implements PersonalizedSearchService {

	private static final int NUM_RESULTS = 15;

	Timer timer;

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		GraphMediator.load();
		timer = new Timer(true);
		// process updates every 10 minutes
		timer.scheduleAtFixedRate(new TimerTask() {

			@Override
			public void run() {
				System.out.println("Running background updates.....");
				GraphUpdater.processUpdates();
			}
		}, 10000, 60000);
	}

	@Override
	public QueryResult search(final int userId, final String query) {
		return ManagedBlock.exceptionHandled(new IBlock<Void, QueryResult>() {

			@Override
			public QueryResult execute() throws Exception {

				// register the query
				Query q = GraphMediator.querySubmitted(query, userId);
				// search google
				ArrayList<GoogleDocument> googleList = searchGoogle(query);

				Set<NodeRef> baseSet = new HashSet<NodeRef>();
				baseSet.add(new NodeRef(userId, NodeType.USER));
				baseSet.add(new NodeRef(q.getId(), NodeType.QUERY));

				// compute page rank
				PersonalizedObjectRank objectRank = new PersonalizedObjectRank(
						baseSet);
				objectRank.process();
				googleList = objectRank.updateGoogleResult(q, googleList);

				// return
				return new QueryResult(q.getId(), googleList);
			}

			@Override
			public void handleException(Exception e) {
				throw new RuntimeException(e);
			}
		});
	}

	@Override
	public void clickGoogleDocument(int userId, int queryId, int documentId) {
		GraphMediator.documentClicked(userId, documentId, queryId);
	}

	@Override
	protected void doGet(HttpServletRequest req, final HttpServletResponse resp)
			throws ServletException, IOException {
		// generate a PajekFile
		String printFile = req.getParameter("print");
		if (printFile != null) {
			doDownload(req, resp, printFile, GraphMediator.print());
			return;
		}
	}

	public static void main(String[] args) {
		PersonalizedSearchServiceImpl impl = new PersonalizedSearchServiceImpl();
		QueryResult d = impl.search(1, "abhijith kashyap");
		for (GoogleDocument g : d.getGoogleRanks()) {
			System.out.println("[" + g.getId() + "] - " + g.getURL());
		}

	}

	@Override
	public User registerUser(int userId) {
		edu.fiu.cis.personalize.server.graph.User u = (edu.fiu.cis.personalize.server.graph.User) GraphMediator
				.get().get(userId, NodeType.USER);
		if (FBTokenStore.isTokenValid(u.getId()))
			return new User(u.getId(), u.getUserName());
		return null;
	}

	private ArrayList<GoogleDocument> searchGoogle(String query)
			throws Exception {
		String feed_query = "https://www.googleapis.com/customsearch/v1?key=AIzaSyCpq0o9gXSvcVruH343mMzTsP0c5UP1kCg&cx=013036536707430787589:_pqjad5hr1a&alt=atom&q="
				+ query;

		@SuppressWarnings("unused")
		int num_iter = NUM_RESULTS % 10 == 0 ? NUM_RESULTS / 10
				: NUM_RESULTS / 10 + 1;
		int count = 1;
		ArrayList<GoogleDocument> list = new ArrayList<GoogleDocument>();
		outer: for (int n = 1; n <= num_iter; n++) {
			URL url = new URL(feed_query + "&start=" + count);
			Feed feed = FeedParser.parse(url);

			int items = feed.getItemCount();
			for (int i = 0; i < items; i++) {
				FeedItem item = feed.getItem(i);
				list.add(new GoogleDocument(count, item.getLink().toString(),
						item.getTitle(), item.getDescriptionAsText()));
				count++;
				if (count > NUM_RESULTS) {
					break outer;
				}
			}
		}

		return list;
	}

	private void doDownload(HttpServletRequest req, HttpServletResponse resp,
			String filename, String data) throws IOException {
		ServletOutputStream op = resp.getOutputStream();
		resp.setContentType("application/octet-stream");
		resp.setContentLength((int) data.length());
		resp.setHeader("Content-Disposition", "attachment; filename=\""
				+ filename + ".paj\"");

		op.write(data.getBytes());
		op.flush();
		op.close();
	}

}
